package com.web;

import com.alibaba.fastjson2.JSONObject;
import com.spring.BeanPostProcessor;
import com.spring.annotation.Component;
import com.web.annotation.Controller;
import com.web.annotation.RequestMapping;
import com.web.annotation.RequestParam;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author chengjy
 * @date 2025/4/15
 */
@Component
public class DispatcherServlet extends HttpServlet implements BeanPostProcessor {

    private Map<String, WebHandler>  webHandlerMap = new HashMap<>();
    private List<HandlerInterceptor> handlerInterceptorList = new java.util.ArrayList<>();

    @Override
    public void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        WebHandler webHandler = findController(req);

        if(webHandler == null){
            resp.setContentType("text/html;charset=utf-8");
            resp.getWriter().write("<h1> 你的请求没有找到! </h1> <br>" + req.getRequestURI().toString());
            return;
        }
        // 拦截器前
        for (HandlerInterceptor handlerInterceptor : handlerInterceptorList) {
            if(!handlerInterceptor.preHandle(req, resp, webHandler)){
                return;
            }
        }

        try {
            Object[] params = analysisParams(webHandler.getMethod() , req);

            Object result = webHandler.getMethod().invoke(webHandler.getObjectBean() , params);

            // 处理器执行后
            for (HandlerInterceptor handlerInterceptor : handlerInterceptorList) {
                if(!handlerInterceptor.postHandle(req, resp, result)){
                    return;
                }
            }

            switch (webHandler.getMethodType()) {
                case JSON -> {
                    resp.setContentType("text/html;charset=utf-8");
                    resp.getWriter().write(JSONObject.toJSONString(result));
                }
                case HTML -> {
                    resp.setContentType("text/html;charset=utf-8");
                    resp.getWriter().write("<h1> "+ result.toString() +" </h1> <br>");
                }
                case LOCAL -> {
                    ModelAndView mv = (ModelAndView) result;
                    String view = mv.getView();

                    InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(view);
                    try(resourceAsStream){
                        String html = new String(resourceAsStream.readAllBytes());
                        html = rendelTemplate(html, mv.getContext());
                        resp.setContentType("text/html;charset=utf-8");
                        resp.getWriter().write(html);
                    }
                }
            }

            // 请求返回前
            for (HandlerInterceptor handlerInterceptor : handlerInterceptorList) {
                handlerInterceptor.afterCompletion(req, resp, webHandler);
            }

        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    // 渲染模版
    private String rendelTemplate(String html, Map<String, Object> context) {
        String result = PlaceholderUtils.replacePlaceholders(html, context);
        return result;
    }

    private Object[] analysisParams(Method method, HttpServletRequest request) {
        Object[] params = new Object[method.getParameterCount()];
        for (int i = 0; i < method.getParameterCount(); i++) {
            Class<?> parameterType = method.getParameterTypes()[i];
            Parameter parameter = method.getParameters()[i];

            String urlParams = null;

            RequestParam requestParam = parameter.getAnnotation(RequestParam.class);
            if (requestParam != null) {
                urlParams = request.getParameter(requestParam.value());
            }else{
                urlParams = request.getParameter(parameterType.getName());
            }

            if (urlParams != null) {
                if( String.class.isAssignableFrom(parameterType)){
                    params[i] = String.valueOf(urlParams );
                }else if (Integer.class.isAssignableFrom(parameterType)){
                    params[i] = Integer.valueOf(urlParams );
                }else{
                    params[i] = null;
                }
            }
        }
        return params;
    }

    private WebHandler findController(HttpServletRequest req) {
        String requestURI = req.getRequestURI();
        return webHandlerMap.get(requestURI);
    }

    @Override
    public Object afterInitializeBean(Object object, String beanName) {
        Class<?> aClass = object.getClass();
        // 判断是否是Controller
        if (aClass.isAnnotationPresent(Controller.class)) {
            String url = aClass.isAnnotationPresent(RequestMapping.class) ? aClass.getAnnotation(RequestMapping.class).value() : "";

            Arrays.stream(aClass.getDeclaredMethods()).filter(method -> method.isAnnotationPresent(RequestMapping.class))
                    .forEach(method -> {
                        RequestMapping annotation = method.getAnnotation(RequestMapping.class);
                        WebHandler webHandler = new WebHandler(object, method);
                        if(webHandlerMap.put( url.concat(annotation.value()) ,  webHandler) != null){
                            throw new RuntimeException("重复的url");
                        }
                    });
        }else if ( HandlerInterceptor.class.isAssignableFrom(aClass)){
            handlerInterceptorList.add((HandlerInterceptor) object);
        }
        return object;
    }
}
